package com.cryptoneedle.garden.service.garden.mapping;

import com.cryptoneedle.garden.constant.CommonConstant;
import com.cryptoneedle.garden.constant.DorisConstant;
import com.cryptoneedle.garden.entity.garden.mapping.MappingColumn;
import com.cryptoneedle.garden.entity.garden.mapping.MappingTable;
import com.cryptoneedle.garden.enums.MappingFieldType;
import com.cryptoneedle.garden.service.crud.garden.doris.*;
import com.cryptoneedle.garden.service.garden.sync.SyncDorisService;
import com.cryptoneedle.garden.service.util.ConfigUtil;
import com.cryptoneedle.garden.vo.MappingTableCreateVo;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>description:  </p>
 *
 * @author CryptoNeedle
 * @date 2025-11-14
 */
@Service
public class MappingService {

    @Resource
    private MappingService mappingService;

    @Autowired
    private AddDorisService add;
    @Autowired
    private DeleteDorisService delete;
    @Autowired
    private FoundDorisService select;
    @Autowired
    private PatchDorisService patch;
    @Autowired
    private SaveDorisService save;

    @Resource
    private ConfigUtil configUtil;
    @Resource
    private JdbcTemplate dorisJdbcTemplate;
    @Autowired
    private SyncDorisService syncDorisService;

    public void createMappingTable(MappingTableCreateVo vo) {
        String mappingDatabase = configUtil.mapping();
        String mappingPrefix = DorisConstant.MAPPING_PREFIX;

        String tableName = vo.getTableName();
        tableName = tableName.toLowerCase();
        // 表名小写
        vo.setTableName(tableName.toLowerCase());

        // 检查表名
        if (!tableName.startsWith(mappingPrefix)) {
            throw new RuntimeException("Table name should start with " + mappingPrefix);
        }

        // 检查映射表不应存在
        MappingTable mappingTable = select.mappingTable(DorisConstant.DEFAULT_CATALOG, mappingDatabase, tableName);
        if (mappingTable != null) {
            throw new RuntimeException("Table already exists");
        }

        // 检查列
        List<MappingTableCreateVo.ColumnConfig> columnConfigs = vo.getColumnConfigs();
        if (columnConfigs == null || columnConfigs.size() < 2) {
            throw new RuntimeException("Columns should more than one column");
        }
        // 检查逻辑
        for (MappingTableCreateVo.ColumnConfig columnConfig : columnConfigs) {
            String column = columnConfig.getColumnName();
            String columnLowerCase = column.toLowerCase();
            // 列名小写
            if (!Strings.CS.equals(column, columnLowerCase)) {
                columnConfig.setColumnName(columnLowerCase);
            }
            if (StringUtils.isBlank(columnConfig.getColumnComment())) {
                throw new RuntimeException("列注释不能为空");
            }

            MappingFieldType mappingFieldType = columnConfig.getMappingFieldType();
            if (mappingFieldType == null) {
                columnConfig.setMappingFieldType(MappingFieldType.IGNORE);
            }
            if (MappingFieldType.MAPPING_DETAIL.equals(mappingFieldType)) {
                throw new RuntimeException("无法显示指定 MAPPING_DETAIL");
            }
        }
        columnConfigs.sort(Comparator
                .comparing(config -> -((MappingTableCreateVo.ColumnConfig) config).getMappingFieldType().getSort())
                .thenComparing(config -> ((MappingTableCreateVo.ColumnConfig) config).getSequence()));

        // 创建表
        String sql = createMappingTableSql(vo);
        dorisJdbcTemplate.execute(sql);
        // 同步表
        syncDorisService.syncDoris();
        // 配置表属性
        mappingTable = select.mappingTable(DorisConstant.DEFAULT_CATALOG, mappingDatabase, tableName);
        if (mappingTable == null) {
            throw new RuntimeException("生成Doris表失败");
        }
        patch.mappingTableSetMappingTableFlag(mappingTable, true);
        // 配置列属性
        Map<String, MappingTableCreateVo.ColumnConfig> configColumnMap = Maps.uniqueIndex(columnConfigs, MappingTableCreateVo.ColumnConfig::getColumnName);
        List<MappingColumn> mappingColumns = select.mappingColumns(DorisConstant.DEFAULT_CATALOG, mappingDatabase, tableName);
        for (MappingColumn mappingColumn : mappingColumns) {
            MappingTableCreateVo.ColumnConfig columnConfig = configColumnMap.get(mappingColumn.getColumnName());
            if (columnConfig != null) {
                patch.mappingColumnSetMappingFieldType(mappingColumn, columnConfig.getMappingFieldType());
            } else {
                patch.mappingColumnSetMappingFieldType(mappingColumn, MappingFieldType.IGNORE);
            }
        }
    }

    private String createMappingTableSql(MappingTableCreateVo vo) {
        String tableName = vo.getTableName();
        String tableComment = vo.getTableComment();
        List<MappingTableCreateVo.ColumnConfig> columnConfigs = vo.getColumnConfigs();

        String varcharTemplate = "%s VARCHAR(65533) COMMENT '%s',\n";
        String arrayTemplate = "`%s` ARRAY<VARCHAR(65533)> COMMENT '%s',\n";
        StringBuilder columnDefinition = new StringBuilder();
        // MAPPING_CODE
        columnConfigs.stream()
                .filter(column -> MappingFieldType.MAPPING_CODE.equals(column.getMappingFieldType()))
                .forEach(column -> {
                    columnDefinition.append(String.format(varcharTemplate, "`" + column.getColumnName() + "`", column.getColumnComment()));
                });
        // MAPPING_DETAIL
        columnConfigs.stream()
                .filter(column -> MappingFieldType.MAPPING_DETAIL.equals(column.getMappingFieldType()))
                .forEach(column -> {
                    columnDefinition.append(String.format(arrayTemplate, "`" + column.getColumnName() + DorisConstant.MAPPING_DETAIL_SUFFIX + "`", column.getColumnComment() + "-[详情]"));
                });
        // STANDARD | IGNORE
        columnConfigs.stream()
                .filter(column -> MappingFieldType.STANDARD.equals(column.getMappingFieldType()) || MappingFieldType.IGNORE.equals(column.getMappingFieldType()))
                .forEach(column -> {
                    columnDefinition.append(String.format(varcharTemplate, "`" + column.getColumnName() + "`", column.getColumnComment()));
                });
        // update_time
        columnDefinition.append("`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '更新时间'");

        String uniqueKeys = columnConfigs.stream()
                .filter(config -> MappingFieldType.MAPPING_CODE.equals(config.getMappingFieldType()))
                .map(column -> "`" + column.getColumnName() + "`")
                .collect(Collectors.joining(","));

        return CommonConstant.CREATE_TABLE_TEMPLATE.formatted(configUtil.mapping(), tableName, columnDefinition, uniqueKeys, tableComment, uniqueKeys, DorisConstant.DEFAULT_MAPPING_BUCKET);
    }
}